import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Scanner;
import java.util.stream.Stream;

public class Search {

    private JSONArray jsonArray;
    private HashMap<String, String> movie2id = new HashMap<>();
    private HashMap<String, String> id2movie = new HashMap<>();
    private HashMap<String, ArrayList<String[]>> movieLibrary = new HashMap<>();


    public Search(String jsonFile, String movieFile) {
        JSONParser parser = new JSONParser();
        try {
            this.jsonArray = (JSONArray) parser.parse(new FileReader(jsonFile));
        } catch (FileNotFoundException ex) {
            System.out.println("json file not found: " + jsonFile);
            System.exit(-1);
        } catch (ParseException ex) {
            System.out.println("json file parse error: " + jsonFile);
            System.exit(-2);
        } catch (IOException ex) {
            System.out.println("json file not found: " + jsonFile);
            System.exit(-1);
        }

        for (Object o : this.jsonArray) {
            JSONObject item = (JSONObject) o;
            String movieID = (String) item.get("_id");
            JSONArray adj = (JSONArray) item.get("recommend");
            ArrayList<String[]> adjacentMovies = new ArrayList<>();
            for (Object a : adj) {
                JSONArray x = (JSONArray) a;
                Iterator<String> tuple = x.iterator();
                String[] ratings = {tuple.next(), String.valueOf(tuple.next())};
                adjacentMovies.add(ratings);
            }
            this.movieLibrary.put(movieID, adjacentMovies);
        }

        try (Stream<String> lines = Files.lines(Paths.get(movieFile), StandardCharsets.UTF_8)) {
            for (String line : (Iterable<String>) lines::iterator) {
                String[] fields = line.split("::");
                this.movie2id.put(fields[1], fields[0]);
                this.id2movie.put(fields[0], fields[1]);
            }
        } catch (FileNotFoundException ex) {
            System.out.println("movie file not found: " + movieFile);
            System.exit(-1);
        } catch (IOException ex) {
            System.out.println("movie file not found: " + movieFile);
            System.exit(-1);
        }
    }


    public void recommend(String movie) {
        if (movie.equals(null)) {
            throw new IllegalArgumentException("null movie!!");
        }
        String toSearch = this.movie2id.getOrDefault(movie, "");
        if (toSearch.equals("")) {
            System.out.println("the movie you like is not in library");
            System.exit(-3);
        }
        ArrayList<String[]> recommendation = this.movieLibrary.get(toSearch);
        if (recommendation.size() == 0) {
            System.out.println("the movie you like has no similar movies");
            System.exit(-3);
        }
        int count = 1;
        for (String[] tuple : recommendation) {
            if (count > 10) return;
            String rid = tuple[0];
            String rating = tuple[1];
            String similarMovie = this.id2movie.getOrDefault(rid, "");
//            System.out.println("Movie: " + similarMovie + "Rating: " + rating + "  ID: " + rid);
            System.out.println(String.format("Movie: %-40s Rating: %-10s ID: %-8s", similarMovie, rating, rid));
            count += 1;
        }
    }

    public static void main(String[] args) {
       String jsonFile = args[0];
       String movieFile = args[1];
        // String jsonFile = "/Users/wangzhiwei/Projects/SE_homework/MovieRecommend/data/recommend.json";
        // String movieFile = "/Users/wangzhiwei/Projects/SE_homework/MovieRecommend/data/movies.dat";
        System.out.println("load training dataset...\n");

        Search search = new Search(jsonFile, movieFile);
        Scanner in = new Scanner(System.in);
        System.out.println("input movie you like to find similar movis");
        System.out.println(">");
        String like = in.nextLine().trim();
        System.out.println("\nRecommends:");
        System.out.println("----------------------------------------------------------------------------");
        search.recommend(like);
    }

}
